/*
* This file is a part of the open-eBackup project.
* This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
* If a copy of the MPL was not distributed with this file, You can obtain one at
* http://mozilla.org/MPL/2.0/.
*
* Copyright (c) [2024] Huawei Technologies Co.,Ltd.
*
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
*/
#include "ApiOperatorManager.h"
#include "DoradoApiOperator.h"
#include "V3ApiOperator.h"
#include "common/Structs.h"
#include "config_reader/ConfigIniReader.h"

namespace {
const std::string MODULE_NAME = "ApiOperatorManager";
const std::set<std::string> OceanStor_PRODUCT_MODE = {"61", "62", "63", "64", "68", "69", "70", "71", "72", "73", "74",
    "82", "84", "85", "86", "87", "88", "89", "90", "92", "93", "94", "95", "96", "97", "98", "99", "100", "101", "102",
    "103", "104", "105", "106", "107", "108", "112", "113", "114", "115", "116", "117", "118", "119", "120", "121",
    "122", "123", "124", "125", "126", "127", "128", "129", "130", "131", "132", "133", "134", "135", "137", "805",
    "OceanStorV3", "OceanStoreV3", "OceanStorV5", "OceanStorV6"};
const std::set<std::string> Dorado_PRODUCT_MODE = {"811", "812", "813", "814", "815", "816", "817", "818", "819", "821",
    "822", "823", "824", "825", "826", "827", "828", "829", "830", "831", "832", "833", "834", "835", "836", "837",
    "838", "839", "840", "913", "1202", "DoradoV3", "DoradoV6", "806", "811", "844", "845", "849", "850", "851", "852",
    "853", "854", "855", "856", "857", "858", "859", "900", "901", "902", "903", "904", "905", "906", "907", "908",
    "909", "910", "911", "912", "913", "914", "915", "916", "917", "918", "919", "920", "922", "923", "924"};

const std::string OCEANSOTR_LEVEL = "LEVEL";
const std::string DORADO_LEVEL = "LEVELGROUPTYPE";
const std::string OCEANSOTR_DORADO_ROLEID = "ROLEID";
}

namespace VirtPlugin {
ApiOperatorManager *ApiOperatorManager::GetInstance()
{
    static ApiOperatorManager instance;
    return &instance;
}

ApiOperatorManager::ApiOperatorManager()
{}

ApiOperatorManager::~ApiOperatorManager()
{}

int32_t ApiOperatorManager::GetRestApiOperator(const ControlDeviceInfo &info, std::shared_ptr <ApiOperator> &spRestApi,
                                               bool isGetFromCache, bool isOpService)
{
    std::lock_guard<std::mutex> guard(m_Mutext);
    std::string errorStr;
    StorageSysInfo storageSysInfo;
    if (isGetFromCache) {
        for (auto &ip : info.m_ipList) {
            std::map < std::string, std::shared_ptr < ApiOperator >> ::iterator
            it = m_mapApiOperator.find(ip + info.m_storageType);
            if (it == m_mapApiOperator.end()) {
                continue;
            }
            spRestApi = it->second;
            spRestApi->SetDeviceInfo(info);
            spRestApi->SetOpService(isOpService);
            INFOLOG("Rest api objcet has exist, ip:%s, type:%s", info.m_ip.c_str(), info.m_storageType.c_str());
            if (spRestApi->GetSystemInfo(storageSysInfo, errorStr) != SUCCESS) {
                ERRLOG("GetSystemInfo failed, need refresh session.");
                spRestApi->ClearCacheSession();
            }
            return Module::SUCCESS;
        }
    }
    InitStorageModel();
    std::string model;
    if (m_doradoStorageModel.end() != m_doradoStorageModel.find(info.m_storageType)) {
        spRestApi = std::make_shared<DoradoApiOperator>(info);
        model = "Dorado";
    } else if (m_oceanStorageModel.end() != m_oceanStorageModel.find(info.m_storageType)) {
        spRestApi = std::make_shared<V3ApiOperator>(info);
        model = "Ocean";
    } else if (info.m_storageType == "UnwareType") {
        spRestApi = std::make_shared<ApiOperator>(info);
    }
    if (spRestApi.get() == nullptr) {
        ERRLOG("Create rest api objcet failed, not found storage model:%s", info.m_storageType.c_str());
        return Module::FAILED;
    }
    spRestApi->SetOpService(isOpService);
    if (isGetFromCache) {
        for (auto& ip : info.m_ipList) {
            m_mapApiOperator[ip + info.m_storageType] = spRestApi;
        }
    }
    DBGLOG("Create rest api objcet success, ip:%s, type:%s, model:%s", info.m_ip.c_str(), info.m_storageType.c_str(),
        model.c_str());
    return Module::SUCCESS;
}

void ApiOperatorManager::GetLevelAndRoleID(const std::string& mode, std::string& level, std::string& roleId) const
{
    if (m_oceanStorageModel.find(mode) != m_oceanStorageModel.end()) {
        level = OCEANSOTR_LEVEL;
        roleId = OCEANSOTR_DORADO_ROLEID;
    } else if (m_doradoStorageModel.find(mode) != m_doradoStorageModel.end()) {
        level = DORADO_LEVEL;
        roleId = OCEANSOTR_DORADO_ROLEID;
    } else {
        level = "";
        roleId = "";
    }
}

void ApiOperatorManager::InitStorageModel()
{
    Module::ConfigReader::getStringValueSet("StorageModel", "OceanStorage", m_oceanStorageModel);
    if (m_oceanStorageModel.size() == 0) {
        WARNLOG("Storage model config not found ocean, use default config.");
        m_oceanStorageModel = OceanStor_PRODUCT_MODE;
    }
    std::string modelList;
    for (const auto &it : m_oceanStorageModel) {
        modelList += (it + ",");
    }
    INFOLOG("Ocean-storage:%s", modelList.c_str());
    Module::ConfigReader::getStringValueSet("StorageModel", "DoradoStorage", m_doradoStorageModel);
    if (m_doradoStorageModel.size() == 0) {
        WARNLOG("Storage model config not found dorado, use default config.");
        m_doradoStorageModel = Dorado_PRODUCT_MODE;
    }
    modelList.clear();
    for (const auto &it : m_doradoStorageModel) {
        modelList += (it + ",");
    }
    INFOLOG("Dora-storage:%s", modelList.c_str());
}
}